package com.ssm.basis.model.util;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import static com.ssm.basis.service.constant.DateTimeConstant.DATE_TIME_FORMAT;
import static com.ssm.basis.service.constant.SecurityConstant.SUPPRESS_WARNING_UNCHECKED;

public abstract class JSONUtil {
    private static final ObjectMapper OBJECT_MAPPER;

    static {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        // 序列化对象的所有字段
        builder.serializationInclusion(JsonInclude.Include.ALWAYS);
        // 所有的日期格式都统一为 yyyy-MM-dd HH:mm:ss
        builder.simpleDateFormat(DATE_TIME_FORMAT);
        OBJECT_MAPPER = builder.createXmlMapper(false).build();

        // OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        // OBJECT_MAPPER.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT));

        // 忽略 未知 异常，如在 json 字符串中存在，但是在 java 对象中不存在对应属性的情况
        OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        // 忽略 transient 关键词属性
        OBJECT_MAPPER.enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER);

        // 取消默认转换 timestamps 形式
        OBJECT_MAPPER.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

        // 忽略空 Bean 转 json 的错误
        OBJECT_MAPPER.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
    }

    /**
     * 对象转 json
     */
    public static <T> String obj2String(T obj) {
        try {
            return obj instanceof String ? (String) obj : OBJECT_MAPPER.writeValueAsString(obj);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 对象转 json，带格式化
     */
    public static <T> String obj2StringPretty(T obj) {
        try {
            return obj instanceof String ? (String) obj : OBJECT_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * json 转对象
     */
    @SuppressWarnings(SUPPRESS_WARNING_UNCHECKED)
    public static <T> T string2Obj(String str, Class<T> clazz) {
        try {
            return String.class.equals(clazz) ? (T) str : OBJECT_MAPPER.readValue(str, clazz);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * json 转嵌套对象，如 Map<User, Category>、List<>、...
     */
    @SuppressWarnings(SUPPRESS_WARNING_UNCHECKED)
    public static <T> T string2Obj(String str, TypeReference<T> typeReference) {
        try {
            return (T) (String.class.equals(typeReference.getType()) ? str : OBJECT_MAPPER.readValue(str, typeReference));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * json 转嵌套对象，如 Map<User, Category>、List<>、...
     */
    public static <T> T string2Obj(String str, Class<?> collectionClass, Class<?>... elementClasses) {
        JavaType javaType = OBJECT_MAPPER.getTypeFactory().constructParametricType(collectionClass, elementClasses);
        try {
            return OBJECT_MAPPER.readValue(str, javaType);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}